package concurrents;

import java.util.Calendar;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 重入锁（同一个线程在获得了锁但没有释放之前，可以再次获得锁）
 * 可重入锁指在同一个线程中，可以重入的锁。
 * 当然，当这个线程获得锁后，其他线程将等待这个锁被释放后，才可以获得这个锁。
 * 1.公平锁 所谓公平的锁，是指，各个希望获得所得线程获得锁的顺序是按到达的顺序获得
 * 2.非公平锁 自由竞争获得锁。
 * @author glogo
 *
 */
public class ReentrantLockTest2 {

	private ReentrantLock lock = null;
	// 用于线程同步访问的共享数据
	public int data = 100;

	public ReentrantLockTest2() {
		// 创建一个自由竞争的可重入锁
		lock = new ReentrantLock();
	}

	public static void main(String[] args) {

		ReentrantLockTest2 rtt2 = new ReentrantLockTest2();
		
		//重入3次锁
		rtt2.testReentry();
		// 能执行到这里而不阻塞，表示锁可重入
		rtt2.testReentry();
		rtt2.testReentry();
		// 释放重入测试的锁，要按重入的数量解锁，否则其他线程无法获取该锁。 
		rtt2.getLock().unlock();
		rtt2.getLock().unlock();
		rtt2.getLock().unlock();
		
		rtt2.test(rtt2);
	}

	public void testReentry() {
		lock.lock();
		Calendar now = Calendar.getInstance();
		System.out.println(now.getTime() + " " + Thread.currentThread()
				+ " get lock.");
	}

	public ReentrantLock getLock() {
		System.out.println("unlock.");
		return lock;
	}

	public void testRun() throws Exception {
		// 加锁
		lock.lock();
		Calendar now = Calendar.getInstance();
		try {
			// 获取锁后显示当前时间 当前调用线程 共享数据的值（并使共享数据 + 1）
			System.out.println(now.getTime() + " " + Thread.currentThread()
					+ " accesses the data " + data++);

			// 模拟其他处理，这里假设休眠一下
			Thread.sleep(1000);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 解锁
			lock.unlock();
		}
	}
	

	public void test(ReentrantLockTest2 rtt2) {
		new Thread(new WorkThread(this)).start();
		new Thread(new WorkThread(rtt2)).start();
		new Thread(new WorkThread(rtt2)).start();
	}

}
